package dissertation.extensions.beans.base.control;

import com.intellij.ide.actions.CreateElementActionBase;
import com.intellij.openapi.actionSystem.DataContext;
import com.intellij.openapi.actionSystem.LangDataKeys;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.project.DumbAware;
import com.intellij.openapi.project.Project;
import com.intellij.psi.*;
import com.intellij.util.IncorrectOperationException;
import dissertation.extensions.beans.base.view.CreateEJBDialogWrapper;
import dissertation.services.ejbclass.EJBClassService;
import dissertation.services.ejbmodule.EJBModuleService;
import dissertation.services.ejbclass.IEJBClassService;
import dissertation.services.ejbmodule.IEJBModuleService;
import org.jetbrains.annotations.NotNull;

import java.util.List;

/**
 * Abstract method to create a new ejb class
 */
public abstract class NewEJBClass extends CreateElementActionBase implements DumbAware {
    private String annotationString;
    private String annotationIncludeString;
    private String ejbClassNameSuffix;
    private String ejbNameSuffix;
    private String title;
    private CreateEJBDialogWrapper dialog;
    private IEJBClassService ejbClassService;
    private IEJBModuleService ejbModuleService;

    public NewEJBClass(String annotationIncludeString, String annotationString,
                       String ejbClassNameSuffix, String ejbNameSuffix, String title) {
        this.annotationIncludeString = annotationIncludeString;
        this.annotationString = annotationString;
        this.ejbClassNameSuffix = ejbClassNameSuffix;
        this.ejbNameSuffix = ejbNameSuffix;
        this.title = title;
        ejbClassService = new EJBClassService();
        ejbModuleService = new EJBModuleService();
    }

    /**
     * Method invoked after triggering the creation action
     * @param project - the destination project
     * @param psiDirectory - the destination directory
     * @return - the elements created
     */
    @NotNull
    @Override
    protected PsiElement[] invokeDialog(Project project, PsiDirectory psiDirectory) {
        MyInputValidator myInputValidator = new MyInputValidator(project, psiDirectory);

        dialog = new CreateEJBDialogWrapper(project, myInputValidator, title, ejbNameSuffix, ejbClassNameSuffix);
        dialog.show();

        return myInputValidator.getCreatedElements();
    }

    /**
     * Method invoked after creating the psi elements
     * @param newName - the name of the class to create
     * @param directory - the destination directory
     * @return - the files created
     * @throws Exception - on error
     */
    @NotNull
    @Override
    protected PsiElement[] create(String newName, PsiDirectory directory) throws Exception {
        try {
            PsiClass newClass = ejbClassService.createClass(directory, dialog.getEJBClassName() + ejbClassNameSuffix);
            ejbClassService.addImportStatement(newClass, annotationIncludeString);
            ejbClassService.addEJBClassAnnotation(newClass, annotationString, dialog.getEJBName() + ejbNameSuffix);
            return new PsiElement[] {newClass.getContainingFile()};
        }
        catch (IncorrectOperationException e) {
            throw e;
        }
        catch (Exception e) {
            return PsiElement.EMPTY_ARRAY;
        }
    }

    /**
     * Method that is invoked before triggering the creation event
     * @param dataContext - the data context
     * @return - true if the current module is an ejb module and it supports the selected bean type, false otherwise
     */
    @Override
    protected boolean isAvailable(DataContext dataContext) {
        if (!super.isAvailable(dataContext)) return false;

        Module currentModule = LangDataKeys.MODULE.getData(dataContext);
        return ejbModuleService.isEJBModule(currentModule) && getSupportedEJBVersions().contains(ejbModuleService.getEJBVersion(currentModule));
    }

    /**
     * Method that returns the supported versions for the bean type
     * @return - the list of supported versions
     */
    public abstract List<String> getSupportedEJBVersions();
}
